
#include "DSound.h"


CSoundSystem *g_pSoundSystem = NULL;


CSoundSystem::CSoundSystem()
{
	m_DirectSound	= NULL;
	m_Primary		= NULL;
}



CSoundSystem::~CSoundSystem()
{
	if (m_DirectSound)
	{
		if (m_Primary) 
			m_Primary->Release();

		m_DirectSound->Release();
	}

	std::list<CSound*>::iterator it;

	for (it = m_SoundList.begin(); it != m_SoundList.end(); ++it)
		delete *it;
}



void CSoundSystem::Initialize(HWND hWnd)
{
	HRESULT hr;

	// Create DirectSound
	if (FAILED(DirectSoundCreate(NULL, &m_DirectSound, NULL)))
		throw "CSoundSystem : Could not create direct sound object";
 
	// Set co-op level
	if (FAILED(IDirectSound_SetCooperativeLevel(m_DirectSound, hWnd, DSSCL_PRIORITY)))
		throw "CSoundSystem : Could not set co-op level";

	// Obtain primary buffer
	DSBUFFERDESC dsbdesc;
	ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
	dsbdesc.dwSize = sizeof(DSBUFFERDESC);
	dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;

	if (FAILED(m_DirectSound->CreateSoundBuffer(&dsbdesc, &m_Primary, NULL)))
		throw "CSoundSystem : Could not obtain primary sound buffer";

	// Set primary buffer format
 	WAVEFORMATEX wfx;
	memset(&wfx, 0, sizeof(WAVEFORMATEX)); 
	wfx.wFormatTag = WAVE_FORMAT_PCM; 
	wfx.nChannels = 2; 
	wfx.nSamplesPerSec = 44100; 
	wfx.wBitsPerSample = 16; 
	wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
	
	hr = m_Primary->SetFormat(&wfx);
	if (FAILED(hr))
		throw "CSoundSystem : Could not set primary buffer format";
}



void CSoundSystem::SetDefaultPath(LPCSTR path)
{
	m_Path = path;
}



CSound* CSoundSystem::LoadSound(const char* filename)
{
	std::list<CSound*>::iterator it;

	for (it = m_SoundList.begin(); it != m_SoundList.end(); ++it)
	{
		if ((*it)->m_Filename == filename)
			return *it;
	}

	HMMIO wavefile;
	wavefile = mmioOpen((char*)filename, 0, MMIO_READ | MMIO_ALLOCBUF);
	
	if (wavefile == NULL)
	{
		char path[MAX_PATH];
		strcpy(path, m_Path);
		strcat(path, filename);

		wavefile = mmioOpen(path, 0, MMIO_READ | MMIO_ALLOCBUF);
		
		if (wavefile == NULL)
		{
			mmioClose(wavefile, 0);
			throw "CSoundSystem : Error loading sound file";
		}
	}
		
	MMCKINFO parent;
	ZeroMemory(&parent, sizeof(MMCKINFO));
	parent.fccType = mmioFOURCC ('W', 'A', 'V', 'E');

	mmioDescend(wavefile, &parent, 0, MMIO_FINDRIFF);

	MMCKINFO child;
	ZeroMemory(&child, sizeof(MMCKINFO));
	child.fccType = mmioFOURCC ('f', 'm', 't', ' ');

	mmioDescend(wavefile, &child, &parent, 0);
	
	WAVEFORMATEX wavefmt;
	mmioRead(wavefile, (char*)&wavefmt, sizeof(wavefmt));
	
	if(wavefmt.wFormatTag != WAVE_FORMAT_PCM)
	{
		mmioClose(wavefile, 0);
		throw "CSoundSystem : Requested file is not a WAVE file";
	}

	mmioAscend(wavefile, &child, 0);
	child.ckid = mmioFOURCC ('d', 'a', 't', 'a');

	mmioDescend(wavefile, &child, &parent, MMIO_FINDCHUNK);
	
	DSBUFFERDESC bufdesc;
	ZeroMemory(&bufdesc, sizeof(DSBUFFERDESC));
	bufdesc.dwSize = sizeof(DSBUFFERDESC);
	bufdesc.dwFlags = 0;
	bufdesc.dwBufferBytes = child.cksize;
	bufdesc.lpwfxFormat = &wavefmt;

	IDirectSoundBuffer* buffer;
	if (FAILED(m_DirectSound->CreateSoundBuffer(&bufdesc, &buffer, NULL)))
	{
		mmioClose(wavefile, 0);
		throw "CSoundSystem : Could not create sound buffer";
	}
	
	void *write1 = 0, *write2 = 0;
	unsigned long length1,length2;

	buffer->Lock(0, child.cksize, &write1, &length1, &write2, &length2, 0);

	if(write1 > 0)
		mmioRead(wavefile, (char*)write1, length1);

	if (write2 > 0)
		mmioRead(wavefile, (char*)write2, length2);

	buffer->Unlock(write1, length1, write2, length2);

	mmioClose(wavefile, 0);

	CSound* sound = new CSound;
	sound->m_Filename = filename;
	sound->m_Sound    = buffer;
	sound->m_bLooping = false;

	m_SoundList.push_back(sound);

	return sound;
}



void CSoundSystem::PlaySound(CSound* sound)
{
	sound->m_Sound->Stop();
	sound->m_Sound->SetCurrentPosition(0);
	sound->m_Sound->Play(0, 0, sound->m_bLooping & DSBPLAY_LOOPING);
}




